﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;

namespace ImageProcessing
{
	public enum OperationType { Affine, Enhancement };
	public enum AffineType { Rotate, Shear, Scale };

	public partial class formMain : Form
	{
		Bitmap bmIn;
		Bitmap bmOrig;
		Bitmap bmDummy;
		bool imageReady;
		bool isChanged;
		double time;
		FilterTypes _filtertypes;

		const int DEFAULTWIDTH = 500;
		const int DEFAULTHEIGHT = 350;


		public formMain()
		{
			bmDummy = new Bitmap(1, 1);

			InitializeComponent();
			toolStripStatusLabel1.Text = "No image";
		}


		//
		//file menu events
		//

		private void openMenuItem_Click(object sender, EventArgs e)
		{
			openFileDialog.Filter = "All Image Files|*.png;*.jpg;*.bmp|Jpeg (*.jpg)|*.jpg|Bitmap Files (*.bmp)|*.bmp|PNG files (*.png)|*.png|TIF files (*.png)|*.tif";

			if (openFileDialog.ShowDialog() == DialogResult.OK)
			{
				bmIn = new Bitmap(openFileDialog.FileName);
				bmOrig = new Bitmap(bmIn);
				toolStripStatusLabel1.Text = openFileDialog.FileName.Substring(openFileDialog.FileName.LastIndexOf(@"\") + 1);
				imageReady = true;
				picboxMain.Invalidate();
			}
		}

		private void exitMenuItem_Click(object sender, EventArgs e)
		{
			Close();
		}

		//
		//paint events
		//
		private void picboxMain_Paint(object sender, PaintEventArgs e)
		{
			if (imageReady)
			{
				picboxMain.BackgroundImage = bmIn;
				picboxMain.Size = bmIn.Size;

				//if (bmIn.Width < 900)
				//    this.Width = bmIn.Width + 50;
				//else
				//    this.Width = 1000;
				//if (bmIn.Height < 700)
				//    this.Height = bmIn.Height + 100;
				//else
				//    this.Height = 800;
			}
			else
			{
				picboxMain.BackgroundImage = bmDummy;
			}
		}

		//
		//Affine Menu Clicks
		//

		private void rotateMenuItem_Click(object sender, EventArgs e)
		{
			ShowEditDialog(OperationType.Affine);
		}

		private void shearMenuItem_Click(object sender, EventArgs e)
		{
			ShowEditDialog(OperationType.Affine);
		}

		private void zoomMenuItem_Click(object sender, EventArgs e)
		{
			ShowEditDialog(OperationType.Affine);
		}


		//
		//helpers
		//
		private bool ShowEditDialog(OperationType optype)
		{
			if (!imageReady) return false;
			AffineDialog eDlg = new AffineDialog(bmIn, optype);
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				//success
				bmIn = new Bitmap(eDlg.ImageOut);
				isChanged = true;
				picboxMain.Invalidate();
				return true;
			}
			return false;

		}

		private void correctionsMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
		{
			if (!imageReady) return;

			ColorEnhanceDialog eDlg = new ColorEnhanceDialog(bmIn);
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				bmIn = new Bitmap(eDlg.ImageOut);
				isChanged = true;
				picboxMain.Invalidate();
			} //end if
		}

		//private void alphaTrimMeanToolStripMenuItem_Click(object sender, EventArgs e)
		//{
		//    if (!isReady) return;

		//    DateTime begin = DateTime.Now;

		//    double[][][] adYIQ = ColorConversions.ImageToYIQ(bmIn);
		//    bmIn = OrderStatFilters.AlphaTrimMean(adYIQ, bmIn.Height, bmIn.Width, 3, bmIn.PixelFormat,4);

		//    TimeSpan dt = (TimeSpan)(DateTime.Now - begin);
		//    time = dt.TotalMilliseconds;
		//    toolStripStatusLabel1.Text = time.ToString();
		//    Invalidate();
		//}

		//private void contraharmonicMenuItem_Click(object sender, EventArgs e)
		//{
		//    if (!isReady) return;

		//    DateTime begin = DateTime.Now;

		//    double[][][] adYIQ = ColorConversions.ImageToYIQ(bmIn);

		//    TimeSpan dt = (TimeSpan)(DateTime.Now - begin);
		//    bmIn = OrderStatFilters.Contraharmonic(adYIQ, bmIn.Height, bmIn.Width, 3, bmIn.PixelFormat, 0);


		//    time = dt.TotalMilliseconds;
		//    toolStripStatusLabel1.Text = time.ToString();
		//    Invalidate();
		//}

		private void filtersMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
		{
			if (!imageReady) return;

			switch (e.ClickedItem.Name)
			{
				case ("medianMenuItem"):
					_filtertypes = FilterTypes.Median;
					break;
				case ("arithmeticmeanMenuItem"):
					_filtertypes = FilterTypes.ArithmeticMean;
					break;
				case ("geometricmeanMenuItem"):
					_filtertypes = FilterTypes.GeometricMean;
					break;
				case ("minMenuItem"):
					_filtertypes = FilterTypes.Min;
					break;
				case ("maxMenuItem"):
					_filtertypes = FilterTypes.Min;
					break;
				case ("contraharmonicMenuItem"):
					_filtertypes = FilterTypes.Contraharmonic;
					break;
				case ("alphatrimmeanMenuItem"):
					_filtertypes = FilterTypes.AlphaMean;
					break;
				case ("midpointMenuItem"):
					_filtertypes = FilterTypes.Midpoint;
					break;
				case ("sobelMenuItem"):
					_filtertypes = FilterTypes.Sobel;
					break;
				case ("prewittMenuItem"):
					_filtertypes = FilterTypes.Prewitt;
					break;
				default:
					break;
			} //end switch

			FilterDialog eDlg = new FilterDialog(bmIn, _filtertypes);
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				bmIn = new Bitmap(eDlg.ImageOut);
				isChanged = true;
				picboxMain.Invalidate();
			} //end if
		}

		private void specialMenuItem_Click(object sender, EventArgs e)
		{
			SpecialEffectsDialog eDlg = new SpecialEffectsDialog(bmIn);
			//	eDlg.ImageIn = bmIn;
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				bmIn = eDlg.ImageOut;
				isChanged = true;
				picboxMain.Invalidate();
			}
		}

		private void testToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//const int nSize = 12;
			//double[, ,] adResult;

//            if (imageReady)
//            {
//                this.Cursor = Cursors.WaitCursor;
//                DateTime begin = DateTime.Now;
//                //bmIn = OrderStatFilters.GeometricMean(adImage, nSize, nSize, 3, PixelFormat.Format24bppRgb);
//                //bmIn = OrderStatFilters.HarmonicMean(adImage, nSize, nSize, 3, PixelFormat.Format24bppRgb);
//                double[, ,] adNormal = BitmapConversions.NormalizeRGB(bmIn);
//                //bmIn = BitmapConversions.UnNormalizeRGB(adNormal, bmIn.Width, bmIn.Height, true, bmIn.PixelFormat);
//                double[, ,] adImage = BitmapConversions.HSIConversion(adNormal, bmIn.Width, bmIn.Height, true,true);
//                double[, ,] adOut = BitmapConversions.HSIConversion(adImage, bmIn.Width, bmIn.Height, false,true);
//                bmIn = BitmapConversions.UnNormalizeRGB(adOut, bmIn.Width, bmIn.Height, true, bmIn.PixelFormat);

//                TimeSpan dt = (TimeSpan)(DateTime.Now - begin);
//                this.Cursor = Cursors.Default;
//                time = dt.TotalMilliseconds;
//                toolStripStatusLabel1.Text = time.ToString();
//                picboxMain.Invalidate();
//            }




//Q5 Final
//double[, ,] adData = new double[nSize,nSize,3] {
//    {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} },
//    {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {2,2,2}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} },
//    {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {2,2,2}, {3,3,3}, {2,2,2}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0} },
//    {{0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {2,2,2}, {3,3,3}, {4,4,4}, {3,3,3}, {2,2,2}, {1,1,1}, {0,0,0}, {0,0,0} },
//    {{0,0,0}, {0,0,0}, {1,1,1}, {2,2,2}, {3,3,3}, {4,4,4}, {7,7,7}, {4,4,4}, {3,3,3}, {2,2,2}, {1,1,1}, {0,0,0} },
//    {{0,0,0}, {1,1,1}, {2,2,2}, {3,3,3}, {4,4,4}, {5,5,5}, {7,7,7}, {5,5,5}, {4,4,4}, {3,3,3}, {2,2,2}, {0,0,0} },
//    {{0,0,0}, {2,2,2}, {3,3,3}, {4,4,4}, {5,5,5}, {6,6,6}, {7,7,7}, {6,6,6}, {5,5,5}, {4,4,4}, {3,3,3}, {0,0,0} },
//    {{0,0,0}, {2,2,2}, {2,2,2}, {4,4,4}, {4,4,4}, {5,5,5}, {0,0,0}, {4,4,4}, {5,5,5}, {5,5,5}, {4,4,4}, {0,0,0} },
//    {{0,0,0}, {2,2,2}, {2,2,2}, {2,2,2}, {6,6,6}, {6,6,6}, {6,6,6}, {6,6,6}, {6,6,6}, {2,2,2}, {2,2,2}, {0,0,0} },
//    {{0,0,0}, {2,2,2}, {7,7,7}, {2,2,2}, {3,3,3}, {4,4,4}, {5,5,5}, {5,5,5}, {7,7,7}, {5,5,5}, {5,5,5}, {0,0,0} },
//    {{0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {2,2,2}, {2,2,2}, {2,2,2}, {3,3,3}, {3,3,3}, {0,0,0} },
//    {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }
//};
//double[,] adB = new double[3, 3] {
//    {-1,-1,3},
//    {1,4,2},
//    {-1,-1,-1}
//};
//double[,] adB2 = new double[3, 3] {
//    {-1,-1,4},
//    {-1,2,2},
//    {2,-1,-1}
//};
//adResult = Morphology.Dilate(adData, adB, nSize, nSize, 3, 3);
//adResult = Morphology.Erode(adData, adB2, nSize, nSize, 3, 3);
//adResult = Morphology.Open(adData, adB, nSize, nSize, 3, 3);
//Console.WriteLine("Filter1 Dilate");
//for (int i = 0; i < nSize; i++)
//{
//    for (int j = 0; j < nSize; j++)
//    {
//        if (adResult[i, j, 0] > 7)
//            Console.Write("7 ");
//        else
//            Console.Write(adResult[i, j, 0] + " ");
//    } //end for
//    Console.Write("\n");
//} //end for


//            //Console.WriteLine("Filter2 Erode");
//            //adResult = Morphology.Erode(adData, adB2, nSize, nSize, 3, 3);
//            //for (int i = 0; i < nSize; i++)
//            //{
//            //    for (int j = 0; j < nSize; j++)
//            //    {
//            //        if (adResult[i, j, 0] < 0)
//            //            Console.Write("0 ");
//            //        else
//            //            Console.Write(adResult[i, j, 0] + " ");
//            //    } //end for
//            //    Console.Write("\n");
//            //} //end for

//            //Console.WriteLine("Filter1 Open");
//            //adResult = Morphology.Open(adData, adB, nSize, nSize, 3, 3);
//            //for (int i = 0; i < nSize; i++)
//            //{
//            //    for (int j = 0; j < nSize; j++)
//            //    {
//            //        if (adResult[i, j, 0] < 0)
//            //            Console.Write("0 ");
//            //        else
//            //            Console.Write(adResult[i, j, 0] + " ");
//            //    } //end for
//            //    Console.Write("\n");
//            //} //end for 



//            //
//            //Q4 Final
//            //

//double[, ,] adData = new double[nSize, nSize, 3] {
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}},
//        {{0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0}, {1,1,1}, {1,1,1}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} },
//        {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }
//};

//double[,] adB = new double[3, 3] {
//    {-1,0,-1},
//    {0,0,-1},
//    {-1,0,-1}
//};

//adResult = Morphology.Open(adData, adB, nSize, nSize, 3, 3);
//adResult = Morphology.Dilate(adData, adB, nSize, nSize, 3, 3);
//adResult = Morphology.Close(adData, adB, nSize, nSize, 3, 3);
//adResult = Morphology.Erode(adData, adB, nSize, nSize, 3, 3);

//for (int i = 0; i < nSize; i++)
//{
//    for (int j = 0; j < nSize; j++)
//    {
//        Console.Write(adResult[i, j, 0] + " ");
//    } //end for
//    Console.Write("\n");
//} //end for




//            //
//            //Q1 Final
//            //
//            int nSize = 12;
//            double[,] adData = new double[12, 12] {
//                {0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0},
//                {0, 0,  0,  0,  0,  1,  2,  1,  0,  0,  0, 0},
//                {0, 0,  0,  0,  1,  2,  3,  2,  1,  0,  0, 0},
//                {0, 0,  0,  1,  2,  3,  4,  3,  2,  1,  0, 0},
//                {0, 0,  1,  2,  3,  4,  7,  4,  3,  2,  1, 0},
//                {0, 1,  2,  3,  4,  5,  7,  5,  4,  3,  2, 0},
//                {0, 2,  3,  4,  5,  6,  7,  6,  5,  4,  3, 0},
//                {0, 2,  2,  4,  4,  5,  0,  4,  5,  5,  4, 0},
//                {0, 2,  2,  2,  6,  6,  6,  6,  6,  2,  2, 0},
//                {0, 2,  7,  2,  3,  4,  5,  5,  7,  5,  5, 0},
//                {0, 1,  1,  1,  0,  0,  2,  2,  2,  3,  3, 0},
//                {0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 0},
//            };

//            Bitmap bmOut = new Bitmap(nSize, nSize, PixelFormat.Format24bppRgb);
//            #region Image pointer setup
//            BitmapData srcBitData;
//            Rectangle rectSrc = new Rectangle(0, 0, bmOut.Width, bmOut.Height);
//            srcBitData = bmOut.LockBits(rectSrc, ImageLockMode.ReadOnly, bmOut.PixelFormat);
//            int srcStride = srcBitData.Stride;

//            IntPtr srcPtr = srcBitData.Scan0;
//            int imageBPP = Image.GetPixelFormatSize(bmOut.PixelFormat);
//            int srcBytePP = imageBPP / 8;
//            #endregion Image pointer setup

//            int k;
//            unsafe
//            {
//                byte* sptr = (byte*)(void*)srcPtr;

//                for (int j = 0; j < bmOut.Height; j++)
//                {
//                    k = j * srcStride;
//                    for (int i = 0; i < bmOut.Width; i++)
//                    {
//                        sptr[k + i * srcBytePP] = (byte)adData[j, i];
//                        sptr[k + i * srcBytePP + 1] = (byte)adData[j, i];
//                        sptr[k + i * srcBytePP + 2] = (byte)adData[j, i];
//                    } //end for
//                } //end for
//            } //end unsafe

//            bmOut.UnlockBits(srcBitData);

//            DateTime begin = DateTime.Now;
//            double[][][] adImage = ColorConversions.ImageToYIQ(bmOut);
//            bmIn = OrderStatFilters.GeometricMean(adImage, nSize, nSize, 3, PixelFormat.Format24bppRgb);
//            bmIn = OrderStatFilters.HarmonicMean(adImage, nSize, nSize, 3, PixelFormat.Format24bppRgb);

//            TimeSpan dt = (TimeSpan)(DateTime.Now - begin);
//            time = dt.TotalMilliseconds;
//            toolStripStatusLabel1.Text = time.ToString();

			//Color mycolor = new Color();

			//for (int j = 0; j < nSize; j++)
			//{
			//    for (int i = 0; i < nSize; i++)
			//    {
			//        mycolor = bmIn.GetPixel(i, j);
			//        Console.Write(mycolor.R  + " ");
			//    } //end for
			//    Console.Write("\n");
			//} //end for

		}

		private void conformalToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ConformalDialog eDlg = new ConformalDialog(bmIn);
			//	eDlg.ImageIn = bmIn;
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				bmIn = eDlg.ImageOut;
				isChanged = true;
				picboxMain.Invalidate();
			}
		}

		private void enhanceMenuItem_Click(object sender, EventArgs e)
		{
			EnhancementDialog eDlg = new EnhancementDialog(bmIn);
			//	eDlg.ImageIn = bmIn;
			if (eDlg.ShowDialog() == DialogResult.OK)
			{
				bmIn = eDlg.ImageOut;
				isChanged = true;
				picboxMain.Invalidate();
			}
		}

		private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			string picName;
			saveFileDialog.Filter = "Jpeg (*.jpg)|*.jpg|Bitmap Files (*.bmp)|*.bmp|PNG files (*.png)|*.png|All Image Files|*.png;*.jpg;*.bmp";
			if (saveFileDialog.ShowDialog() == DialogResult.OK)
			{
				picName = saveFileDialog.FileName;
				bmIn.Save(picName);
			} //end if
		}

	}
}
